import requests
import threading
import random
import time

invalid_time = 175
# request_proxy_url = "http://api.shenlongip.com/ip?key=cxw1xgyk&protocol=2&mr=1&pattern=txt&count=1&sign=59316cd4f2e043676fb744ba801645be"
# request_proxy_url = "http://api.shenlongip.com/ip?key=cxw1xgyk&protocol=1&mr=1&pattern=txt&count=1&sign=de46bef5685f288d54485b7c7fc3f922"
# request_proxy_url = "http://api.shenlongip.com/ip?key=cg1n8pe0&protocol=1&mr=1&pattern=txt&count=1&sign=de46bef5685f288d54485b7c7fc3f922"
# request_proxy_url = "http://api.shenlongip.com/ip?key=cg1n8pe0&isp=%E7%94%B5%E4%BF%A1&protocol=1&mr=1&pattern=txt&count=1&sign=de46bef5685f288d54485b7c7fc3f922"
# request_proxy_url = "http://api.shenlongip.com/ip?key=izk4aas1&area=310100&isp=%E7%94%B5%E4%BF%A1&protocol=1&mr=1&pattern=txt&count=1&sign=de46bef5685f288d54485b7c7fc3f922"
request_proxy_url = "http://api.shenlongip.com/ip?key=izk4aas1&protocol=1&mr=1&pattern=txt&count=1&sign=de46bef5685f288d54485b7c7fc3f922"
# test_proxy_url = "https://www.1lou.info/thread-558558.htm"
test_proxy_url = "https://www.1lou.info/forum-5.htm"

class ProxyPool:
    def __init__(self, max_size=10):
        self.proxies = []  # 存储代理的列表，格式为 (ip, port, expire_time)
        self.max_size = max_size
        self.lock = threading.RLock()  # 线程锁确保线程安全
        self.get_proxy_url = request_proxy_url
        self.headers = {'User-Agent': 'Mozilla/5.0'}
        self.error_count = 0

    def _fetch_proxy(self):
        """从API获取一个新的代理IP"""
        try:
            resp = requests.get(self.get_proxy_url, timeout=10, headers=self.headers)
            if resp.status_code == 200:
                ip_port = resp.text.strip().split(':')
                if len(ip_port) == 2:
                    proxy_host = ip_port[0]
                    proxy_port = int(ip_port[1])
                    return proxy_host, proxy_port
        except Exception as e:
            print(f"获取代理失败: {e}")
        return None

    def _schedule_removal(self, proxy, delay=invalid_time):
        """安排代理在指定延迟后移除"""
        timer = threading.Timer(delay, self._remove_proxy, args=[proxy])
        timer.daemon = True
        timer.start()

    def _remove_proxy(self, proxy):
        """从池中移除指定代理"""
        with self.lock:
            if proxy in self.proxies:
                self.proxies.remove(proxy)
                print(f"代理已过期: {proxy[0]}:{proxy[1]}")

    def _add_proxy(self):
        """向代理池添加一个新代理"""
        success = False
        new_proxy = None
        try_count = 0
        while not success:
            if try_count > 3:
                print(f"尝试申请 proxy 连续失败已超过 {try_count}...程序终止")
                return False, None
            new_proxy = self._fetch_proxy()
            try_count += 1
            if not new_proxy:
                print(f"申请新的 proxy 失败: {new_proxy}")
                return False, None
            print(f"申请了新的 proxy: {new_proxy}")
            time.sleep(1.2)
            success = new_proxy is not None
            proxies = {
                'http': f'http://{new_proxy[0]}:{new_proxy[1]}',
                'https': f'http://{new_proxy[0]}:{new_proxy[1]}'
            }
            try:
                response = requests.get(test_proxy_url, proxies=proxies, timeout=3)
                success &= (response.status_code == 200)
                if success:
                    print(f"测试新申请 proxy 成功: {proxies}")
                else:
                    time.sleep(3)
            except Exception as ex:
                success = False
                self.error_count += 1
                print(f"error: 测试新申请 proxy 失败，总失败次数 {self.error_count}: {proxies}, {ex}")
                time.sleep(3)

        proxy = (*new_proxy, time.time() + invalid_time)  # (ip, port, expire_time)

        with self.lock:
            # 清理过期代理
            current_time = time.time()
            self.proxies = [p for p in self.proxies if p[2] > current_time]

            # 检查是否已满
            if len(self.proxies) >= self.max_size:
                print("代理池已满，无法添加新代理")
                return False, None

            self.proxies.append(proxy)
            self._schedule_removal(proxy)
            print(f"代理已添加: {proxy[0]}:{proxy[1]}")
        return True, proxy

    def _get_valid_proxies(self):
        with self.lock:
            current_time = time.time()
            # 过滤出未过期的代理
            valid_proxies = [p for p in self.proxies if p[2] > current_time]
            return valid_proxies

    def get_random_proxy(self):
        """随机获取一个有效代理"""
        valid_proxies = self._get_valid_proxies()

        if not valid_proxies: # 如果所有proxy都过期了，那么开始新增proxy并且经过测试
            success, new_proxy = self._add_proxy()
            if success:
                valid_proxies = self._get_valid_proxies()
            else:
                return None

        # 随机选择一个代理
        proxy = random.choice(valid_proxies)
        return proxy[0], proxy[1]

    def get_requests_proxy(self):
        valid_proxy = self.get_random_proxy()
        # print(f"proxy: {valid_proxy}")
        if valid_proxy:
            proxies = {
                'http': f'http://{valid_proxy[0]}:{valid_proxy[1]}',
                'https': f'http://{valid_proxy[0]}:{valid_proxy[1]}'
            }
            return proxies
        return None


# 使用示例
if __name__ == "__main__":
    pool = ProxyPool(max_size=10)
    for _ in range(10):
        proxy = pool.get_random_proxy()
        print(proxy)

    # # 添加初始代理
    # for _ in range(3):
    #     pool._add_proxy()
    #     time.sleep(1)  # 避免请求过快
    #
    # # 测试获取代理
    # for i in range(5):
    #     proxy = pool.get_random_proxy()
    #     if proxy:
    #         print(f"使用代理: {proxy[0]}:{proxy[1]}")
    #     else:
    #         print("无可用代理")
    #     time.sleep(30)
    #
    # # 持续添加代理（在实际应用中可能需要定时添加）
    # while True:
    #     if len(pool.proxies) < 5:  # 当代理少于5个时补充
    #         pool.add_proxy()
    #     time.sleep(60)